#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <unistd.h>
#include <queue>
#include <pthread.h>
#include <sys/types.h>
#include "thread.hpp"
using namespace std;

#define THREADNUM 5

template <class T>
class threadPool
{
public:
private:
    static void *routine(void *args)
    {
        threadPool<T> *pool = static_cast<threadPool<T> *>(args);
        T task;
        int count=0;
        while (1)
        {
            sleep(1);
            pool->pop();
            //直接退出证明thread封装正确
            break;
        }
    }

public:
    void start()
    {
        for (int i = 0; i < THREADNUM; i++)
        {
            thread t(routine, (void *)this);
            _info[i]._tid = t.gettid();
            _info[i]._threadName = "thread" + to_string(i);
            _threads.push_back(move(t));
        }
    }

    void finish()
    {
        void *ret;
        for (auto t : _threads)
        {
            t.join();
        }
    }

    void push(const T &task) // 这里生产任务只需要一直生产即可，不需要访问控制
    {
        pthread_mutex_lock(&_mutex);
        _task.push(task);
        pthread_cond_signal(&_cond);
        pthread_mutex_unlock(&_mutex);
    }

    void pop()
    {
        pthread_mutex_lock(&_mutex);
        while (_task.empty())
        {
            pthread_cond_wait(&_cond, &_mutex);
        }
        T top = _task.front();
        _task.pop();
        top();
        top.getAnswer(getThreadName(pthread_self()));
        pthread_mutex_unlock(&_mutex);
    }

    string getThreadName(pthread_t tid)
    {
        for (auto info : _info)
        {
            if (info._tid == tid)
                return info._threadName;
        }
        return "no thred";
    }

    int tasknum()
    {
        return _task.size();
    }

    static threadPool<T> *getThreadPool()
    {
        if (_ppool == nullptr)
        {
            _ppool = new threadPool<T>();
        }
        return _ppool;
    }

private:
    // 单例模式将构造拷贝构造私有化，外部无法直接构造出新的对象
    threadPool(int num = THREADNUM)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        _info.resize(THREADNUM);
    }

    threadPool(threadPool<T> &) = delete;
    threadPool<T> operator=(threadPool<T> &) = delete;

    struct threadInfo
    {
        string _threadName;
        pthread_t _tid;
    };

    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    queue<T> _task;
    vector<threadInfo> _info;

    vector<thread> _threads;

    // 单例只需要唯一的实例化对象
    static threadPool<T> *_ppool;
};

template <class T>
threadPool<T> *threadPool<T>::_ppool = nullptr;